// tests/setup.js - 增强版测试环境配置（完全静默）
import { MongoMemoryServer } from 'mongodb-memory-server';
import mongoose from 'mongoose';

// 全局测试配置
global.testConfig = {
  JWT_SECRET: 'test-jwt-secret-key-for-testing-only',
  MONGO_MEMORY_SERVER: null,
  DEFAULT_TIMEOUT: 30000,
};

// 设置环境变量
process.env.NODE_ENV = 'test';
process.env.SQ_JWT_SECRET = global.testConfig.JWT_SECRET;
process.env.SQ_SITE_NAME = 'Test Tracker';
process.env.SQ_BASE_URL = 'http://localhost:3001';
process.env.SQ_API_URL = 'http://localhost:3001';
process.env.SQ_ALLOW_REGISTER = 'open';
process.env.SQ_DISABLE_EMAIL = 'true';
process.env.SQ_MINIMUM_RATIO = '-1';
process.env.SQ_MAXIMUM_HIT_N_RUNS = '-1';
process.env.SQ_BP_EARNED_PER_GB = '10';
process.env.SQ_BP_EARNED_PER_FILLED_REQUEST = '50';
process.env.SQ_BP_COST_PER_INVITE = '100';
process.env.SQ_BP_COST_PER_GB = '50';
process.env.SQ_SITE_WIDE_FREELEECH = 'false';
process.env.SQ_ALLOW_UNREGISTERED_VIEW = 'false';
process.env.SQ_ANNOUNCE_INTERVAL = '1800';
process.env.SQ_MIN_ANNOUNCE_INTERVAL = '900';

// 屏蔽所有 Node.js 警告
process.env.NODE_NO_WARNINGS = '1';
process.env.NODE_OPTIONS = '--no-warnings --no-deprecation';

// 关闭Mongoose警告并设置所有选项避免deprecation
mongoose.set('strictQuery', false);
mongoose.set('useFindAndModify', false);  // 避免 findOneAndUpdate 警告
mongoose.set('useCreateIndex', true);
mongoose.set('useNewUrlParser', true);
mongoose.set('useUnifiedTopology', true);

// Jest配置
jest.setTimeout(global.testConfig.DEFAULT_TIMEOUT);

// 保存原始控制台方法
const originalConsoleError = console.error;
const originalConsoleWarn = console.warn;
const originalConsoleLog = console.log;
const originalConsoleInfo = console.info;
const originalConsoleDebug = console.debug;

// 定义需要完全屏蔽的关键词列表
const BLOCKED_KEYWORDS = [
  // 调试信息
  '[DEBUG]',
  'DEBUG',
  
  // 中文错误消息
  '偏好设置为空',
  '用户不存在',
  '找不到用户',
  
  // 英文错误消息
  'User not found',
  'could not embellish',
  'embellishTorrentsWithTrackerScrape',
  
  // 技术栈相关
  'DeprecationWarning',
  'ExperimentalWarning',
  'MongoDB Memory Server',
  'jest-mongodb',
  'experimental',
  'warning',
  'Warning',
  'MongoDB',
  'jest',
  
  // 文件路径
  'src/controllers/',
  'tests/setup.js',
  'node_modules/',
  
  // 其他
  'tracker',
  'Mongoose:',
  'findOneAndUpdate',
  'findOneAndDelete',
  'useFindAndModify'
];

// 检查是否包含被屏蔽的关键词
function containsBlockedKeyword(message) {
  if (typeof message !== 'string') return false;
  
  return BLOCKED_KEYWORDS.some(keyword => 
    message.includes(keyword)
  );
}

// HTTP请求日志的正则表达式
const HTTP_LOG_PATTERN = /^(GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD)\s+\/.+\s+\d{3}\s+[\d.]+\s*ms/;

// 完全静默的 console.error
console.error = (...args) => {
  const message = args[0];
  
  // 如果包含任何被屏蔽的关键词，完全忽略
  if (containsBlockedKeyword(message)) {
    return;
  }
  
  // 在测试环境中，几乎屏蔽所有 console.error
  // 只允许非常严重的系统级错误通过
  if (typeof message === 'string' && 
      (message.includes('FATAL') || message.includes('CRITICAL'))) {
    originalConsoleError.apply(console, args);
  }
  
  // 其他所有错误都被屏蔽
  return;
};

// 完全静默的 console.warn
console.warn = (...args) => {
  // 在测试环境中完全屏蔽所有警告
  return;
};

// 完全静默的 console.info 和 console.debug
console.info = () => { return; };
console.debug = () => { return; };

// 高度过滤的 console.log - 只保留HTTP请求日志和重要测试信息
console.log = (...args) => {
  const message = args[0];
  
  if (typeof message === 'string') {
    // 如果包含被屏蔽的关键词，完全忽略
    if (containsBlockedKeyword(message)) {
      return;
    }
    
    // 只允许HTTP请求日志
    if (HTTP_LOG_PATTERN.test(message.trim())) {
      originalConsoleLog.apply(console, args);
      return;
    }
    
    // 允许重要的测试框架消息
    if (
      message.includes('PASS') || 
      message.includes('FAIL') ||
      message.includes('Tests:') ||
      message.includes('Time:') ||
      message.includes('Test Suites:') ||
      (message.startsWith('✅') || message.startsWith('❌') || message.startsWith('📊'))
    ) {
      originalConsoleLog.apply(console, args);
      return;
    }
  }
  
  // 忽略所有其他日志输出
  return;
};

// 屏蔽 process 级别的所有警告事件
const originalProcessEmit = process.emit;
process.emit = function(name, data, ...args) {
  // 屏蔽所有警告相关的事件
  if (
    name === 'warning' || 
    name === 'DeprecationWarning' ||
    name === 'ExperimentalWarning' ||
    name === 'MaxListenersExceededWarning' ||
    name === 'UnhandledPromiseRejectionWarning'
  ) {
    return false;
  }
  
  // 屏蔽包含特定关键词的事件
  if (data && typeof data === 'object' && data.message) {
    if (containsBlockedKeyword(data.message)) {
      return false;
    }
  }
  
  return originalProcessEmit.apply(process, [name, data, ...args]);
};

// 静默处理所有类型的警告和错误事件
process.on('warning', () => {
  // 完全忽略所有警告
});

process.on('unhandledRejection', (reason, promise) => {
  // 在测试环境中静默处理未捕获的Promise rejection
  // 完全不输出任何信息
});

process.on('uncaughtException', (error) => {
  // 在测试环境中静默处理未捕获的异常
  // 对于非致命错误，完全忽略
  if (error && error.message) {
    if (containsBlockedKeyword(error.message) || 
        error.message.includes('listen EADDRINUSE')) {
      return;
    }
  }
});

// 屏蔽 stderr 写入（如果需要的话）
const originalStderrWrite = process.stderr.write;
process.stderr.write = function(chunk, encoding, callback) {
  if (typeof chunk === 'string' && containsBlockedKeyword(chunk)) {
    // 屏蔽包含被屏蔽关键词的 stderr 输出
    if (typeof callback === 'function') {
      callback();
    }
    return true;
  }
  
  return originalStderrWrite.call(process.stderr, chunk, encoding, callback);
};

// 测试前的全局设置
beforeAll(async () => {
  if (mongoose.connection.readyState !== 0) {
    await mongoose.disconnect();
  }
});

// 测试后的全局清理
afterAll(async () => {
  if (mongoose.connection.readyState !== 0) {
    await mongoose.disconnect();
  }
  
  if (global.testConfig.MONGO_MEMORY_SERVER) {
    await global.testConfig.MONGO_MEMORY_SERVER.stop();
  }
});

// 测试工具函数
export const testUtils = {
  // 等待函数
  wait: (ms) => new Promise(resolve => setTimeout(resolve, ms)),
  
  // 生成随机字符串
  randomString: (length = 10) => {
    const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    let result = '';
    for (let i = 0; i < length; i++) {
      result += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return result;
  },
  
  // 生成测试用户数据
  generateUserData: (override = {}) => ({
    username: testUtils.randomString(8),
    email: `${testUtils.randomString(8)}@test.com`,
    password: 'password123',
    ...override,
  }),
  
  // 生成测试种子数据
  generateTorrentData: (override = {}) => ({
    name: `Test Torrent ${testUtils.randomString(5)}`,
    description: 'A test torrent for automated testing',
    type: 'Other',
    source: 'Private',
    torrent: Buffer.from('fake torrent data').toString('base64'),
    tags: 'test,automated',
    ...override,
  }),
  
  // 生成测试公告数据
  generateAnnouncementData: (override = {}) => ({
    title: `Test Announcement ${testUtils.randomString(5)}`,
    body: 'This is a test announcement for API testing',
    pinned: false,
    allowComments: true,
    ...override,
  }),
  
  // 创建测试数据库连接
  async createTestDatabase() {
    if (!global.testConfig.MONGO_MEMORY_SERVER) {
      global.testConfig.MONGO_MEMORY_SERVER = await MongoMemoryServer.create({
        binary: {
          version: '4.4.18',
          downloadDir: './mongodb-binaries',
        },
        instance: {
          dbName: 'test-sqtracker',
        },
      });
    }
    
    const uri = global.testConfig.MONGO_MEMORY_SERVER.getUri();
    
    if (mongoose.connection.readyState === 0) {
      await mongoose.connect(uri, {
        useNewUrlParser: true,
        useUnifiedTopology: true,
        useCreateIndex: true,
        useFindAndModify: false,  // 明确设置避免警告
      });
    }
    
    return uri;
  },
  
  // 清理测试数据
  async cleanupTestData() {
    if (mongoose.connection.readyState === 1) {
      const collections = mongoose.connection.collections;
      await Promise.all(
        Object.values(collections).map(collection => collection.deleteMany({}))
      );
    }
  },
};

// 模拟Tracker对象
class MockTracker {
  constructor() {
    this.torrents = {};
  }

  _onRequest(params, callback) {
    const { action, info_hash } = params;
    
    if (action === 'announce') {
      callback(null, {
        action: 'announce',
        interval: 1800,
        'min interval': 900,
        complete: 0,
        incomplete: 0,
        peers: Buffer.alloc(0),
      });
    } else if (action === 'scrape') {
      callback(null, {
        action: 'scrape',
        files: {},
      });
    } else {
      callback(new Error('Invalid action'));
    }
  }

  addTorrent(infoHash) {
    this.torrents[infoHash] = {
      complete: 0,
      incomplete: 0,
      peers: new Map(),
    };
  }

  removeTorrent(infoHash) {
    delete this.torrents[infoHash];
  }
}

// 模拟邮件服务
class MockMailService {
  constructor() {
    this.sentEmails = [];
  }

  async sendMail(options) {
    this.sentEmails.push({
      ...options,
      sentAt: new Date(),
    });
    return { messageId: `mock-${Date.now()}` };
  }

  getSentEmails() {
    return this.sentEmails;
  }

  clearSentEmails() {
    this.sentEmails = [];
  }

  getLastEmail() {
    return this.sentEmails[this.sentEmails.length - 1];
  }
}

// 测试数据固定装置
const testFixtures = {
  users: {
    admin: {
      username: 'admin',
      email: 'admin@test.com',
      password: 'password123',
      role: 'admin',
      emailVerified: true,
      uid: 'admin12345',
      bonusPoints: 1000,
      remainingInvites: 10,
    },
    user: {
      username: 'testuser',
      email: 'user@test.com',
      password: 'password123',
      role: 'user',
      emailVerified: true,
      uid: 'user123456',
      bonusPoints: 100,
      remainingInvites: 2,
    },
    unverified: {
      username: 'unverified',
      email: 'unverified@test.com',
      password: 'password123',
      role: 'user',
      emailVerified: false,
      uid: 'unverified1',
      bonusPoints: 0,
      remainingInvites: 0,
    },
  },
  
  torrents: {
    movie: {
      name: 'Test Movie 2023',
      description: 'A great test movie for API testing',
      type: 'Movies',
      source: 'Private',
      infoHash: 'a'.repeat(40),
      size: 5000000000, // 5GB
      files: [
        { path: 'Test.Movie.2023.1080p.BluRay.x264.mkv', size: 4500000000 },
        { path: 'Test.Movie.2023.nfo', size: 5000 },
      ],
      tags: ['action', 'thriller', '2023'],
      binary: 'fake-torrent-data-movie',
    },
    tv: {
      name: 'Test TV Show S01E01',
      description: 'A test TV episode for API testing',
      type: 'TV',
      source: 'Private',
      infoHash: 'b'.repeat(40),
      size: 1000000000, // 1GB
      files: [
        { path: 'Test.TV.Show.S01E01.720p.HDTV.x264.mkv', size: 950000000 },
        { path: 'Test.TV.Show.S01E01.srt', size: 50000 },
      ],
      tags: ['comedy', 'series'],
      binary: 'fake-torrent-data-tv',
    },
  },
  
  announcements: {
    welcome: {
      title: 'Welcome to Test Tracker',
      body: 'This is a welcome announcement for testing the announcement system',
      pinned: true,
      allowComments: true,
    },
    update: {
      title: 'System Update Notice',
      body: 'The system will be updated tonight for testing purposes',
      pinned: false,
      allowComments: false,
    },
  },
  
  ratings: [
    { score: 5, comment: 'Excellent quality and content!' },
    { score: 4, comment: 'Very good, recommended' },
    { score: 3, comment: 'Average quality' },
    { score: 2, comment: 'Below expectations' },
    { score: 1, comment: 'Poor quality' },
  ],

  requests: {
    movie: {
      title: 'Looking for Classic Movie',
      body: 'I am looking for a specific classic movie from the 1980s',
    },
    tv: {
      title: 'TV Series Request',
      body: 'Need the complete season of a popular TV series',
    },
  },
};

// 导出所有工具
export { MockTracker, MockMailService, testFixtures };
export default testUtils;